<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>贪吃蛇 - 游戏空间</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script src="/static/common.js"></script>
    <style>
        body {
            background: linear-gradient(135deg, #e0e7ff 0%, #f8fafc 100%);
        }
        #game-area {
            background: #fff;
            border-radius: 1.5rem;
            box-shadow: 0 4px 32px 0 #6366f133;
            margin: 0 auto;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 2rem;
            max-width: 400px;
        }
        canvas {
            background: #f1f5f9;
            border-radius: 1rem;
            box-shadow: 0 2px 12px 0 #6366f122;
        }
        /* 自定义弹窗样式 */
        #back-modal {
            display: none;
            position: fixed;
            z-index: 1000;
            left: 0; top: 0; right: 0; bottom: 0;
            background: rgba(0,0,0,0.3);
            align-items: center;
            justify-content: center;
        }
        #back-modal .modal-content {
            background: #fff;
            border-radius: 1rem;
            padding: 2rem 2.5rem;
            box-shadow: 0 8px 32px 0 #6366f155;
            text-align: center;
            min-width: 240px;
        }
        #back-modal .modal-btn {
            margin: 0 0.5rem;
            padding: 0.5rem 1.5rem;
            border-radius: 999px;
            font-weight: bold;
            background: linear-gradient(90deg, #6366f1 0%, #818cf8 100%);
            color: #fff;
            border: none;
            cursor: pointer;
            transition: background 0.2s, transform 0.2s;
        }
        #back-modal .modal-btn:hover {
            background: linear-gradient(90deg, #818cf8 0%, #6366f1 100%);
            transform: scale(1.05);
        }
        .modern-card {
            border-radius: 1.5rem;
            box-shadow: 0 4px 32px 0 #6366f133;
            background: #fff;
        }
        .player-card {
            background: #fff;
            border-radius: 1rem;
            padding: 1rem;
            text-align: center;
            min-width: 140px;
            box-shadow: 0 2px 12px rgba(99, 102, 241, 0.1);
            transition: all 0.3s ease;
        }
        .player-card.ready {
            border: 2px solid #4ade80;
        }
        .player-card.not-ready {
            border: 2px solid #e5e7eb;
        }
        .player-card .avatar {
            width: 48px;
            height: 48px;
            border-radius: 50%;
            background: #f3f4f6;
            margin: 0 auto 0.5rem;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.5rem;
            color: #6366f1;
        }
        .player-card .name {
            font-weight: 600;
            color: #1f2937;
            margin-bottom: 0.25rem;
            font-size: 0.9rem;
        }
        .player-card .status {
            font-size: 0.75rem;
            color: #6b7280;
        }
        .player-card .status.ready {
            color: #4ade80;
        }
    </style>
</head>
<body class="font-sans text-dark min-h-screen flex flex-col">
    <div id="game-header" style="display:flex;align-items:center;justify-content:space-between;padding:8px 16px;">
        <span id="room-user-count" class="text-gray-700 text-sm"></span>
    </div>
    <header class="modern-nav text-white shadow-md p-4 flex flex-col items-center bg-indigo-600 relative">
        <div class="flex items-center mb-2">
            <span class="text-xl font-bold ml-4">贪吃蛇</span>
        </div>
        <div id="user-info" class="text-lg font-bold text-indigo-100 mb-1"></div>
        <div id="score-info" class="flex gap-4 text-base font-semibold"></div>
        <div id="game-tip" class="text-sm bg-indigo-100 text-indigo-700 rounded px-2 py-1 mt-1"></div>
        <div class="flex items-center absolute right-4 top-4">
            <button id="match-btn" class="bg-white text-indigo-700 px-4 py-1 rounded shadow hover:bg-indigo-100 transition">匹配</button>
            <button id="ready-btn1" class="ml-2 modern-btn px-4 py-1">准备</button>
            <button id="delete-room-btn" class="ml-2 bg-red-500 text-white px-4 py-1 rounded shadow hover:bg-red-600 transition hidden">删除房间</button>
            <button id="back-select-btn" class="ml-2 modern-btn px-4 py-1">返回大厅</button>
        </div>
    </header>
    <main class="flex-grow flex flex-col items-center justify-center">
        <div id="game-area" class="mt-8">
            <h2 class="text-lg font-bold mb-4 text-primary flex items-center"><i class="fa fa-apple mr-2"></i>贪吃蛇对战</h2>
            <div id="player-list" class="flex justify-between w-full max-w-xs mb-4 gap-4">
                <div class="player-card not-ready" id="player1-card">
                    <div class="avatar">
                        <i class="fa fa-user"></i>
                    </div>
                    <div class="name" id="player1-name">等待加入...</div>
                    <div class="status" id="player1-status">未准备</div>
                </div>
                <div class="player-card not-ready" id="player2-card">
                    <div class="avatar">
                        <i class="fa fa-user"></i>
                    </div>
                    <div class="name" id="player2-name">等待加入...</div>
                    <div class="status" id="player2-status">未准备</div>
                </div>
            </div>
            <canvas id="snake-canvas" width="320" height="320" tabindex="0" class="mb-4"></canvas>
            <div class="mt-4 flex flex-col items-center">
                <button id="start-btn" class="modern-btn px-6 py-2 mt-4">开始游戏</button>
                <button id="restart-btn" class="modern-btn px-6 py-2 mt-2 hidden">重新开始</button>
            </div>
            <!-- 只显示一个操纵杆 -->
            <div class="text-xs text-gray-400 mt-1">WASD/方向键/操纵杆</div>
            <div id="joystick1" class="flex flex-col items-center mb-2 select-none">
                <div class="flex justify-center">
                    <button class="joystick-btn1 w-10 h-10 m-1 rounded-full bg-gradient-to-br from-primary to-secondary text-white text-xl shadow-lg flex items-center justify-center active:scale-90 transition" data-dir="UP">↑</button>
                </div>
                <div class="flex justify-center">
                    <button class="joystick-btn1 w-10 h-10 m-1 rounded-full bg-gradient-to-br from-primary to-secondary text-white text-xl shadow-lg flex items-center justify-center active:scale-90 transition" data-dir="LEFT">←</button>
                    <span class="w-10 h-10 m-1"></span>
                    <button class="joystick-btn1 w-10 h-10 m-1 rounded-full bg-gradient-to-br from-primary to-secondary text-white text-xl shadow-lg flex items-center justify-center active:scale-90 transition" data-dir="RIGHT">→</button>
                </div>
                <div class="flex justify-center">
                    <button class="joystick-btn1 w-10 h-10 m-1 rounded-full bg-gradient-to-br from-primary to-secondary text-white text-xl shadow-lg flex items-center justify-center active:scale-90 transition" data-dir="DOWN">↓</button>
                </div>
                
            </div>

        </div>
    </main>
    <!-- 自定义返回弹窗 -->
    <div id="back-modal">
        <div class="modal-content">
            <div class="text-lg font-bold mb-4">请选择返回位置</div>
            <button class="modal-btn" id="to-game-lobby">返回游戏大厅</button>
            <button class="modal-btn" id="to-chat-lobby">返回聊天大厅</button>
            <div class="mt-4"><button class="text-gray-400 hover:text-primary" id="close-modal">取消</button></div>
        </div>
    </div>
    <div id="matching-modal" style="display:none;position:fixed;z-index:1000;left:0;top:0;right:0;bottom:0;background:rgba(0,0,0,0.3);align-items:center;justify-content:center;">
        <div id="matching-modal-content" style="background:#fff;padding:2rem;border-radius:1rem;min-width:300px;"></div>
    </div>
    <script>
        // ==== 用户信息与全局变量 ====
        const user = getCurrentUser();
        if (!user) {
            window.location.href = '/static/index.html';
        }
        const userId = user.userId;
        const userName = user.username;
        function getRoomId() {
            const url = new URL(window.location.href);
            return url.searchParams.get('room_id');
        }
        const roomId = getRoomId();
        document.addEventListener('DOMContentLoaded', function() {
            initRoomOwnerActions(roomId, userId, 'delete-room-btn', '/static/index.html');
            // 通用房间用户管理
            initGameRoomUserManager({
                roomId,
                userId,
                userName,
                readyBtnId: 'ready-btn1',
                playerCardIds: ['player1-card', 'player2-card'],
                playerNameIds: ['player1-name', 'player2-name'],
                playerStatusIds: ['player1-status', 'player2-status'],
                roomUserCountId: 'room-user-count',
                onAllReady: function(players) {
                    // 所有玩家准备好时的回调（可选）
                }
            });
            // 返回大厅弹窗相关事件绑定
            const backSelectBtn = document.getElementById('back-select-btn');
            const backModal = document.getElementById('back-modal');
            if (backSelectBtn && backModal) {
                backSelectBtn.onclick = () => { backModal.style.display = 'flex'; };
                document.getElementById('close-modal').onclick = () => { backModal.style.display = 'none'; };
                document.getElementById('to-game-lobby').onclick = () => { safeCloseWSAndGo('/'); };
                document.getElementById('to-chat-lobby').onclick = () => { safeCloseWSAndGo('/'); };
                backModal.onclick = (e) => { if (e.target === backModal) backModal.style.display = 'none'; };
            }
        });

        // 消息类型
        const MessageTypeText = 0;
        const MessageTypeJoin = 1;
        const MessageTypeLeave = 2;

        const MessageTypeGameOp = 100;
        const MessageTypeGameState = 101;
        const MessageTypeReadyChanged = 102;

        // UI元素
        const canvas = document.getElementById('snake-canvas');
        const ctx = canvas.getContext('2d');
        const readyBtn1 = document.getElementById('ready-btn1');
        const startBtn = document.getElementById('start-btn');
        const restartBtn = document.getElementById('restart-btn');
        const playerList = document.getElementById('player-list');
        const joystick1 = document.getElementById('joystick1');
        const matchBtn = document.getElementById('match-btn');
        // 只显示自己和第2位玩家（如有更多玩家可扩展）

        // 游戏状态
        let gameState = {
            status: 'waiting', // waiting, playing, gameover
            snakes: {},
            foods: [],
            scores: {},
            gridSize: 16, // 16x16网格
            cellSize: 20, // 每个格子20px
        };
        let myReady = false;
        let myAlive = true;
        let matching = false;
        let gameInterval = null;
        let localInterval = null;

        // 初始化游戏
        function initGame() {
            gameState = {
                status: 'waiting',
                snakes: {},
                foods: [],
                scores: {},
                gridSize: 16,
                cellSize: 20
            };
            
            // 添加当前玩家的蛇
            gameState.snakes[userId] = {
                segments: [
                    {x: 8, y: 8},
                    {x: 7, y: 8},
                    {x: 6, y: 8}
                ],
                direction: 'RIGHT',
                alive: true,
                color: '#6366f1'
            };
            
            // 初始化分数
            gameState.scores[userId] = 0;
            
            // 生成食物
            gameState.foods = [generateFood(), generateFood()];
            
            renderGame();
        }
        
        // 生成食物
        function generateFood() {
            // 随机生成食物位置
            const x = Math.floor(Math.random() * gameState.gridSize);
            const y = Math.floor(Math.random() * gameState.gridSize);
            
            // 检查是否与蛇重叠
            for (const uid in gameState.snakes) {
                const snake = gameState.snakes[uid];
                for (const segment of snake.segments) {
                    if (segment.x === x && segment.y === y) {
                        // 如果重叠，重新生成
                        return generateFood();
                    }
                }
            }
            
            return {x, y};
        }
        
        // 游戏循环
        function gameLoop() {
            if (gameState.status !== 'playing') return;
            
            // 移动蛇
            for (const uid in gameState.snakes) {
                const snake = gameState.snakes[uid];
                if (!snake.alive) continue;
                
                // 获取蛇头
                const head = {...snake.segments[0]};
                
                // 根据方向移动
                switch (snake.direction) {
                    case 'LEFT': head.x--; break;
                    case 'RIGHT': head.x++; break;
                    case 'UP': head.y--; break;
                    case 'DOWN': head.y++; break;
                }
                
                // 检查碰撞 - 墙壁
                if (head.x < 0 || head.x >= gameState.gridSize || head.y < 0 || head.y >= gameState.gridSize) {
                    snake.alive = false;
                    if (uid === userId) {
                        myAlive = false;
                        document.getElementById('game-tip').textContent = '你撞墙了，游戏结束！';
                    }
                    continue;
                }
                
                // 检查碰撞 - 自己
                for (let i = 0; i < snake.segments.length; i++) {
                    if (snake.segments[i].x === head.x && snake.segments[i].y === head.y) {
                        snake.alive = false;
                        if (uid === userId) {
                            myAlive = false;
                            document.getElementById('game-tip').textContent = '你咬到自己了，游戏结束！';
                        }
                        continue;
                    }
                }
                
                // 检查碰撞 - 其他蛇
                for (const otherUid in gameState.snakes) {
                    if (otherUid === uid) continue; // 跳过自己
                    
                    const otherSnake = gameState.snakes[otherUid];
                    for (const segment of otherSnake.segments) {
                        if (segment.x === head.x && segment.y === head.y) {
                            snake.alive = false;
                            if (uid === userId) {
                                myAlive = false;
                                document.getElementById('game-tip').textContent = '你撞到其他玩家了，游戏结束！';
                            }
                            break;
                        }
                    }
                    
                    if (!snake.alive) break;
                }
                
                if (!snake.alive) continue;
                
                // 检查是否吃到食物
                let ate = false;
                for (let i = 0; i < gameState.foods.length; i++) {
                    const food = gameState.foods[i];
                    if (food.x === head.x && food.y === head.y) {
                        // 吃到食物，增加分数
                        gameState.scores[uid] = (gameState.scores[uid] || 0) + 1;
                        // 生成新食物
                        gameState.foods[i] = generateFood();
                        // 蛇身增长
                        snake.segments.unshift(head);
                        ate = true;
                        break;
                    }
                }
                
                if (!ate) {
                    // 没吃到食物，移动蛇
                    snake.segments.unshift(head);
                    snake.segments.pop();
                }
            }
            
            // 检查游戏是否结束
            let aliveCount = 0;
            for (const uid in gameState.snakes) {
                if (gameState.snakes[uid].alive) aliveCount++;
            }
            
            if (aliveCount <= 0 || (Object.keys(gameState.snakes).length > 1 && aliveCount <= 1)) {
                gameState.status = 'gameover';
                document.getElementById('game-tip').textContent = '游戏结束！';
                clearInterval(gameInterval);
                gameInterval = null;
                document.getElementById('restart-btn').classList.remove('hidden');
            }
            
            // 更新UI
            renderGame();
            renderUserInfoAndScore();
        }
        
        // 渲染游戏
        function renderGame() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 绘制网格背景
            ctx.fillStyle = '#f1f5f9';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            ctx.strokeStyle = '#e2e8f0';
            for (let i = 0; i <= gameState.gridSize; i++) {
                // 垂直线
                ctx.beginPath();
                ctx.moveTo(i * gameState.cellSize, 0);
                ctx.lineTo(i * gameState.cellSize, canvas.height);
                ctx.stroke();
                
                // 水平线
                ctx.beginPath();
                ctx.moveTo(0, i * gameState.cellSize);
                ctx.lineTo(canvas.width, i * gameState.cellSize);
                ctx.stroke();
            }
            
            if (!gameState) return;
            
            // 渲染食物
            (gameState.foods || []).forEach(food => {
                ctx.fillStyle = '#f59e42';
                ctx.beginPath();
                ctx.arc(
                    food.x * gameState.cellSize + gameState.cellSize/2, 
                    food.y * gameState.cellSize + gameState.cellSize/2, 
                    gameState.cellSize/2 - 2, 
                    0, 2 * Math.PI
                );
                ctx.fill();
            });
            
            // 渲染所有蛇
            let idx = 0;
            Object.entries(gameState.snakes || {}).forEach(([uid, snake]) => {
                const isCurrentPlayer = uid === userId;
                const headColor = isCurrentPlayer ? '#6366f1' : '#22c55e';
                const bodyColor = isCurrentPlayer ? '#a5b4fc' : '#bbf7d0';
                
                for (let j = 0; j < snake.segments.length; j++) {
                    const segment = snake.segments[j];
                    const isHead = j === 0;
                    
                    ctx.fillStyle = isHead ? headColor : bodyColor;
                    ctx.fillRect(
                        segment.x * gameState.cellSize + 1, 
                        segment.y * gameState.cellSize + 1, 
                        gameState.cellSize - 2, 
                        gameState.cellSize - 2
                    );
                    
                    // 为蛇头添加眼睛
                    if (isHead) {
                        ctx.fillStyle = '#ffffff';
                        
                        // 根据方向绘制眼睛
                        const eyeSize = gameState.cellSize / 5;
                        const eyeOffset = gameState.cellSize / 4;
                        
                        let leftEyeX, leftEyeY, rightEyeX, rightEyeY;
                        
                        switch (snake.direction) {
                            case 'RIGHT':
                                leftEyeX = segment.x * gameState.cellSize + gameState.cellSize - eyeOffset;
                                leftEyeY = segment.y * gameState.cellSize + eyeOffset;
                                rightEyeX = segment.x * gameState.cellSize + gameState.cellSize - eyeOffset;
                                rightEyeY = segment.y * gameState.cellSize + gameState.cellSize - eyeOffset;
                                break;
                            case 'LEFT':
                                leftEyeX = segment.x * gameState.cellSize + eyeOffset;
                                leftEyeY = segment.y * gameState.cellSize + eyeOffset;
                                rightEyeX = segment.x * gameState.cellSize + eyeOffset;
                                rightEyeY = segment.y * gameState.cellSize + gameState.cellSize - eyeOffset;
                                break;
                            case 'UP':
                                leftEyeX = segment.x * gameState.cellSize + eyeOffset;
                                leftEyeY = segment.y * gameState.cellSize + eyeOffset;
                                rightEyeX = segment.x * gameState.cellSize + gameState.cellSize - eyeOffset;
                                rightEyeY = segment.y * gameState.cellSize + eyeOffset;
                                break;
                            case 'DOWN':
                                leftEyeX = segment.x * gameState.cellSize + eyeOffset;
                                leftEyeY = segment.y * gameState.cellSize + gameState.cellSize - eyeOffset;
                                rightEyeX = segment.x * gameState.cellSize + gameState.cellSize - eyeOffset;
                                rightEyeY = segment.y * gameState.cellSize + gameState.cellSize - eyeOffset;
                                break;
                        }
                        
                        ctx.beginPath();
                        ctx.arc(leftEyeX, leftEyeY, eyeSize, 0, 2 * Math.PI);
                        ctx.fill();
                        
                        ctx.beginPath();
                        ctx.arc(rightEyeX, rightEyeY, eyeSize, 0, 2 * Math.PI);
                        ctx.fill();
                    }
                }
                idx++;
            });
            
            // 游戏结束显示
            if (gameState.status === 'gameover') {
                ctx.fillStyle = 'rgba(0,0,0,0.6)';
                ctx.fillRect(0, 120, 320, 80);
                ctx.fillStyle = '#fff';
                ctx.font = '20px sans-serif';
                ctx.textAlign = 'center';
                ctx.fillText('游戏结束', canvas.width/2, 150);
                
                // 显示获胜者
                let winner = null;
                let highestScore = -1;
                
                for (const uid in gameState.scores) {
                    if (gameState.scores[uid] > highestScore) {
                        highestScore = gameState.scores[uid];
                        winner = uid;
                    }
                }
                
                if (winner) {
                    const winnerName = winner === userId ? '你' : (gameState.snakes[winner]?.name || '对手');
                    ctx.fillText(`${winnerName} 获胜!`, canvas.width/2, 180);
                }
            }
        }
        
        // 渲染用户信息和分数
        function renderUserInfoAndScore() {
            const userInfo = document.getElementById('user-info');
            const scoreInfo = document.getElementById('score-info');
            
            userInfo.textContent = `玩家: ${userName}`;
            
            // 清空分数信息
            scoreInfo.innerHTML = '';
            
            // 添加所有玩家分数
            for (const uid in gameState.scores) {
                const score = gameState.scores[uid];
                const isCurrentPlayer = uid === userId;
                const playerName = isCurrentPlayer ? '你' : (gameState.snakes[uid]?.name || '对手');
                const color = isCurrentPlayer ? 'text-indigo-100' : 'text-green-100';
                
                const scoreElement = document.createElement('div');
                scoreElement.className = `${color}`;
                scoreElement.textContent = `${playerName}: ${score}分`;
                scoreInfo.appendChild(scoreElement);
            }
        }

        // 发送操作，添加重试机制
        function sendGameOp(op, dir, ready) {
            // 准备专用消息格式
            if (op === 'ready') {
                const readyMessage = {
                type: MessageTypeGameOp,
                    user_id: userId,
                    content: JSON.stringify({ 
                        op: 'ready', 
                        user_id: userId,
                        ready: ready,
                        user_name: userName // 添加用户名，方便后端处理
                    }),
                    ready: ready // 顶层添加ready字段，便于后端处理
                };
                
                // 立即更新本地UI状态，确保响应速度
                updatePlayerReadyStatus(userId, ready);
                updatePlayersUI();
                
                // 保存到localStorage，确保刷新后状态不丢失
                saveReadyStatusToLocalStorage(userId, ready);
                
                // 发送消息到服务器
                sendMessageWithRetry(readyMessage, () => {
                    console.log("准备状态发送成功");
                });
                return;
            }
            
            // 其他操作的消息格式
            const message = {
                type: MessageTypeGameOp,
                user_id: userId,
                content: JSON.stringify({ 
                    op, 
                    dir,
                    user_id: userId
                })
            };
            
            sendMessageWithRetry(message);
        }
        
        // 保存准备状态到localStorage
        function saveReadyStatusToLocalStorage(userId, ready) {
            try {
                localStorage.setItem(`snake_ready_${roomId}_${userId}`, ready ? "true" : "false");
                console.log("准备状态已保存到localStorage:", ready);
            } catch (e) {
                console.error("保存准备状态到localStorage失败:", e);
            }
        }
        
        // 从localStorage加载准备状态
        function loadReadyStatusFromLocalStorage(userId) {
            try {
                const savedStatus = localStorage.getItem(`snake_ready_${roomId}_${userId}`);
                if (savedStatus !== null) {
                    const isReady = savedStatus === "true";
                    console.log("从localStorage加载准备状态:", isReady);
                    return isReady;
                }
            } catch (e) {
                console.error("从localStorage加载准备状态失败:", e);
            }
            return false;
        }
        
        // 发送消息并添加重试机制
        function sendMessageWithRetry(message, successCallback = null) {
            const sendWithRetry = (retryCount = 0) => {
                try {
                    if (!ws) {
                        console.warn("WebSocket不存在，尝试重新创建连接");
                        createWebSocketConnection();
                        if (retryCount < 3) {
                            setTimeout(() => sendWithRetry(retryCount + 1), 1000);
                        } else {
                            console.error("WebSocket创建失败，已达到最大重试次数");
                        }
                        return;
                    }
                    
                    if (ws.readyState === WebSocket.OPEN) {
                        ws.send(JSON.stringify(message));
                        console.log("发送消息:", message);
                        
                        // 如果有成功回调，执行它
                        if (successCallback) {
                            setTimeout(successCallback, 50);
                        }
                    } else if (ws.readyState === WebSocket.CONNECTING) {
                        console.log("WebSocket正在连接中，等待连接完成后重试");
                        if (retryCount < 5) {
                            setTimeout(() => sendWithRetry(retryCount + 1), 500);
                        } else {
                            console.error("WebSocket连接超时，已达到最大重试次数");
                        }
                    } else if (retryCount < 3) {
                        console.warn("WebSocket未连接，尝试重连后重试");
                        createWebSocketConnection(); // 尝试重新连接
                        setTimeout(() => sendWithRetry(retryCount + 1), 1000);
                    } else {
                        console.error("WebSocket未连接，已达到最大重试次数");
                    }
                } catch (err) {
                    console.error("发送消息失败:", err);
                    if (retryCount < 3) {
                        setTimeout(() => sendWithRetry(retryCount + 1), 1000);
                    }
                }
            };
            
            sendWithRetry();
        }

        // 玩家状态管理
        let players = [];
        
        // 强制更新房间用户列表
        function forceUpdateRoomUsers() {
            fetchRoomUsers().then(users => {
                updatePlayersUI();
                // 保存到localStorage
                savePlayersToLocalStorage();
            }).catch(err => {
                console.error("强制更新房间用户列表失败:", err);
            });
        }
        
        // 获取房间用户列表
        async function fetchRoomUsers() {
            try {
                console.log("获取房间用户列表");
                const response = await fetch(`/api/rooms/users?room_id=${roomId}`);
                
                if (!response.ok) {
                    throw new Error('获取房间用户列表失败');
                }
                
                const users = await response.json();
                console.log("获取到用户列表:", users);
                
                // 更新本地玩家列表，保留已有的准备状态
                if (Array.isArray(users)) {
                    // 创建一个映射存储当前玩家的准备状态
                    const readyStatusMap = {};
                    players.forEach(player => {
                        readyStatusMap[player.user_id] = player.ready;
                    });
                    
                    // 更新玩家列表，保留准备状态
                    players = users.map(user => {
                        return {
                            user_id: user.user_id,
                            user_name: user.user_name,
                            join_time: user.join_time || Date.now(),
                            ready: readyStatusMap[user.user_id] || false
                        };
                    });
                    
                    // 按加入时间排序
                    players.sort((a, b) => a.join_time - b.join_time);
                }
                
                return players;
            } catch (error) {
                console.error("获取房间用户列表失败:", error);
                return players; // 返回当前缓存的玩家列表
            }
        }
        
        // 更新玩家准备状态
        function updatePlayerReadyStatus(userId, isReady) {
            console.log("更新玩家准备状态:", userId, isReady);
            
            // 查找并更新玩家准备状态
            const player = players.find(p => p.user_id === userId);
            if (player) {
                player.ready = isReady;
                console.log("玩家状态已更新:", player);
            } else {
                console.warn("找不到玩家:", userId);
                // 如果找不到玩家，可能是新加入的，强制更新玩家列表
                setTimeout(forceUpdateRoomUsers, 300);
            }
        }
        
        // 更新UI显示
        function updatePlayersUI() {
            console.log("更新玩家UI，当前玩家列表:", players);
            
            // 更新房间人数显示
            document.getElementById('room-user-count').textContent = `房间人数：${players.length}`;
            
            // 更新玩家卡片
            updatePlayerCards();
            
            // 检查是否所有玩家都准备好了
            checkAllPlayersReady();
        }
        
        // 更新玩家卡片
        function updatePlayerCards() {
            const player1Card = document.getElementById('player1-card');
            const player1Name = document.getElementById('player1-name');
            const player1Status = document.getElementById('player1-status');
            
            const player2Card = document.getElementById('player2-card');
            const player2Name = document.getElementById('player2-name');
            const player2Status = document.getElementById('player2-status');
            
            // 更新玩家1卡片
            if (players.length > 0) {
                const player1 = players[0];
                player1Name.textContent = player1.user_name || '未知玩家';
                player1Status.textContent = player1.ready ? '已准备' : '未准备';
                player1Card.className = `player-card ${player1.ready ? 'ready' : 'not-ready'}`;
                player1Status.className = `status ${player1.ready ? 'ready' : ''}`;
                player1Card.setAttribute('data-user-id', player1.user_id);
                
                // 如果是当前用户，更新本地ready状态
                if (player1.user_id === userId) {
                    myReady = player1.ready;
                    readyBtn1.textContent = myReady ? '取消准备' : '准备';
                }
            } else {
                player1Name.textContent = '等待加入...';
                player1Status.textContent = '未准备';
                player1Card.className = 'player-card not-ready';
                player1Status.className = 'status';
                player1Card.removeAttribute('data-user-id');
            }
            
            // 更新玩家2卡片
            if (players.length > 1) {
                const player2 = players[1];
                player2Name.textContent = player2.user_name || '未知玩家';
                player2Status.textContent = player2.ready ? '已准备' : '未准备';
                player2Card.className = `player-card ${player2.ready ? 'ready' : 'not-ready'}`;
                player2Status.className = `status ${player2.ready ? 'ready' : ''}`;
                player2Card.setAttribute('data-user-id', player2.user_id);
                
                // 如果是当前用户，更新本地ready状态
                if (player2.user_id === userId) {
                    myReady = player2.ready;
                    readyBtn1.textContent = myReady ? '取消准备' : '准备';
                }
            } else {
                player2Name.textContent = '等待加入...';
                player2Status.textContent = '未准备';
                player2Card.className = 'player-card not-ready';
                player2Status.className = 'status';
                player2Card.removeAttribute('data-user-id');
            }
        }
        
        // 检查是否所有玩家都准备好了
        function checkAllPlayersReady() {
            // 如果只有一个玩家，不需要检查
            if (players.length <= 1) {
                return false;
            }
            
            // 检查是否所有玩家都准备好了
            const allReady = players.every(player => player.ready);
            
            if (allReady) {
                console.log("所有玩家已准备好，可以开始游戏");
                document.getElementById('game-tip').textContent = '所有玩家已准备，游戏即将开始';
                
                // 如果是房主，自动开始游戏
                if (isCreator && players.length > 1) {
                    setTimeout(() => {
                        sendGameOp('start');
                    }, 1000);
                }
            }
            
            return allReady;
        }
        
        // 初始化玩家列表
        async function initPlayers() {
            players = await fetchRoomUsers();
            updatePlayersUI();
        }
        
        // 定期更新玩家列表（作为备用机制）
        let lastUpdate = 0;
function pollPlayers() {
    requestAnimationFrame(async (timestamp) => {
        if (timestamp - lastUpdate > 5000) {
            if (ws.readyState !== WebSocket.OPEN) {
                console.log("WebSocket连接已断开，使用优化后的轮询机制");
                await initPlayers();
            }
            lastUpdate = timestamp;
        }
        pollPlayers();
    });
}
// 启动优化后的轮询机制
pollPlayers();



        // 自动切换单人/多人模式
        let isSingleMode = true;
        function checkMode() {
            // 根据玩家数量判断模式
            if (players.length <= 1) {
                // 单人模式
                isSingleMode = true;
                document.getElementById('ready-btn1').classList.add('hidden');
                document.getElementById('start-btn').classList.remove('hidden');
                document.getElementById('game-tip').textContent = '单人模式：点击开始游戏';
                if (!localInterval) {
                    startLocalGame();
                }
            } else {
                // 多人模式
                isSingleMode = false;
                document.getElementById('ready-btn1').classList.remove('hidden');
                document.getElementById('start-btn').classList.add('hidden');
                document.getElementById('game-tip').textContent = '多人模式：请准备后开始';
                if (localInterval) {
                    clearInterval(localInterval);
                    localInterval = null;
                }
            }
            renderUserInfoAndScore();
        }
        // 本地推进逻辑（单人模式）
        function startLocalGame() {
            if (localInterval) clearInterval(localInterval);
            localInterval = setInterval(() => {
                if (!gameState) return;
                // 简单推进本地蛇
                const uid = Object.keys(gameState.snakes || {})[0];
                if (!uid) return;
                const snake = gameState.snakes[uid];
                if (!snake || !snake.alive) return;
                // 模拟向前移动
                let head = { ...snake.segments[0] };
                let dx = 0, dy = 0;
                switch (snake.direction) {
                    case 'LEFT': dx = -1; break;
                    case 'RIGHT': dx = 1; break;
                    case 'UP': dy = -1; break;
                    case 'DOWN': dy = 1; break;
                }
                head.x += dx; head.y += dy;
                // 撞墙
                if (head.x < 0 || head.x > 15 || head.y < 0 || head.y > 15) {
                    snake.alive = false;
                    clearInterval(localInterval);
                    localInterval = null;
                    document.getElementById('game-tip').textContent = '游戏结束';
                    renderGame();
                    return;
                }
                // 撞自己
                for (let i = 1; i < snake.segments.length; i++) {
                    if (snake.segments[i].x === head.x && snake.segments[i].y === head.y) {
                        snake.alive = false;
                        clearInterval(localInterval);
                        localInterval = null;
                        document.getElementById('game-tip').textContent = '游戏结束';
                        renderGame();
                        return;
                    }
                }
                // 吃食物
                let ate = false;
                for (let i = 0; i < (gameState.foods || []).length; i++) {
                    const food = gameState.foods[i];
                    if (food.x === head.x && food.y === head.y) {
                        snake.segments.unshift(head);
                        gameState.foods[i] = { x: Math.floor(Math.random() * 16), y: Math.floor(Math.random() * 16) };
                        gameState.scores[uid]++;
                        ate = true;
                        break;
                    }
                }
                if (!ate) {
                    snake.segments.unshift(head);
                    snake.segments.pop();
                }
                renderGame();
            }, 200);
        }



        // 检查WebSocket连接状态
        function checkWebSocketConnection() {
            if (!ws || ws.readyState !== WebSocket.OPEN) {
                console.warn("WebSocket连接已断开或不存在，尝试重新连接");
                createWebSocketConnection();
            } else {
                // 连接正常，发送ping检查连接活跃度
                try {
                    ws.send(JSON.stringify({
                        type: 999, // 心跳类型
                        content: "ping"
                    }));
                } catch (err) {
                    console.error("发送ping检查失败:", err);
                    // 连接可能有问题，尝试重新连接
                    createWebSocketConnection();
                }
            }
        }
        
        // 定期检查WebSocket连接状态
        setInterval(checkWebSocketConnection, 30000);

        // 保存玩家状态到localStorage
        function savePlayersToLocalStorage() {
            try {
                localStorage.setItem(`snake_players_${roomId}`, JSON.stringify(players));
                console.log("玩家状态已保存到localStorage");
            } catch (e) {
                console.error("保存玩家状态到localStorage失败:", e);
            }
        }
        
        // 从localStorage加载玩家状态
        function loadPlayersFromLocalStorage() {
            try {
                const savedPlayers = localStorage.getItem(`snake_players_${roomId}`);
                if (savedPlayers) {
                    const parsedPlayers = JSON.parse(savedPlayers);
                    if (Array.isArray(parsedPlayers) && parsedPlayers.length > 0) {
                        console.log("从localStorage加载玩家状态:", parsedPlayers);
                        players = parsedPlayers;
                        return true;
                    }
                }
            } catch (e) {
                console.error("从localStorage加载玩家状态失败:", e);
            }
            return false;
        }
        
        // 初始化页面
        document.addEventListener('DOMContentLoaded', () => {
            console.log("页面加载完成，初始化玩家状态");
            
            // 加载本地准备状态
            const localReadyStatus = loadReadyStatusFromLocalStorage(userId);
            if (localReadyStatus !== null) {
                myReady = localReadyStatus;
                console.log("从localStorage加载准备状态:", myReady);
            }
            
            // 先尝试从localStorage加载玩家列表
            if (!loadPlayersFromLocalStorage()) {
                // 如果没有缓存数据，则从服务器获取
                initPlayers();
            } else {
                // 有缓存数据，更新UI
                updatePlayersUI();
                // 然后异步更新最新数据
                setTimeout(forceUpdateRoomUsers, 500);
            }
        });
        
        // 如果DOM已加载，立即初始化
        if (document.readyState === 'complete' || document.readyState === 'interactive') {
            console.log("页面已加载，立即初始化玩家状态");
            
            // 加载本地准备状态
            const localReadyStatus = loadReadyStatusFromLocalStorage(userId);
            if (localReadyStatus !== null) {
                myReady = localReadyStatus;
                console.log("从localStorage加载准备状态:", myReady);
            }
            
            // 先尝试从localStorage加载玩家列表
            if (!loadPlayersFromLocalStorage()) {
                // 如果没有缓存数据，则从服务器获取
                initPlayers();
            } else {
                // 有缓存数据，更新UI
                updatePlayersUI();
                // 然后异步更新最新数据
                setTimeout(forceUpdateRoomUsers, 500);
            }
        }
        
        // 在玩家状态更新时保存到localStorage
        const originalUpdatePlayerReadyStatus = updatePlayerReadyStatus;
        updatePlayerReadyStatus = function(userId, isReady) {
            originalUpdatePlayerReadyStatus(userId, isReady);
            savePlayersToLocalStorage();
        };

        // 准备按钮点击处理
        readyBtn1.onclick = function() {
            console.log("准备按钮被点击");
            
            // 本地切换
            myReady = !myReady;
            console.log("准备状态切换为:", myReady);

            // 更新按钮文本
            this.textContent = myReady ? '取消准备' : '准备';
            
            // 发送准备状态到服务器
            console.log("发送准备状态到服务器:", myReady);
            sendGameOp('ready', null, myReady);
        };
        startBtn.onclick = function() {
            if (isSingleMode) {
                // 单人本地开始
                initGame();
                gameState.status = 'playing';
                document.getElementById('game-tip').textContent = '游戏开始！';
                
                if (gameInterval) clearInterval(gameInterval);
                gameInterval = setInterval(gameLoop, 200);
                
                this.classList.add('hidden');
                document.getElementById('restart-btn').classList.add('hidden');
            } else {
                // 多人模式，发送开始游戏命令
                sendGameOp('start', null, null);
                
                // 立即更新本地UI状态
                document.getElementById('game-tip').textContent = '游戏开始！';
                this.classList.add('hidden');
                
                // 等待服务器响应，不立即启动游戏循环
                console.log("已发送开始游戏命令，等待服务器响应...");
            }
        };
        restartBtn.onclick = function() {
            if (isSingleMode) {
                initGame();
                gameState.status = 'playing';
                document.getElementById('game-tip').textContent = '游戏重新开始！';
                
                if (gameInterval) clearInterval(gameInterval);
                gameInterval = setInterval(gameLoop, 200);
                
                this.classList.add('hidden');
                document.getElementById('start-btn').classList.add('hidden');
            } else {
                myReady = false;
                sendGameOp('ready', false);
                this.classList.add('hidden');
            }
        };
        matchBtn.onclick = function() {
            if (!matching) {
                // 开始匹配
                fetch(`/api/rooms/${roomId}/matching`, { method: 'POST' }).then(() => {
                    matching = true;
                    matchBtn.textContent = '取消匹配';
                    matchBtn.classList.add('bg-gray-300', 'text-gray-500');
                    matchBtn.classList.remove('bg-white', 'text-indigo-700', 'hover:bg-indigo-100');
                    matchBtn.disabled = false;
                });
            } else {
                // 取消匹配
                fetch(`/api/rooms/${roomId}/cancel-matching`, { method: 'POST' }).then(() => {
                    matching = false;
                    matchBtn.textContent = '匹配';
                    matchBtn.classList.remove('bg-gray-300', 'text-gray-500', 'bg-red-100', 'text-red-600');
                    matchBtn.classList.add('bg-white', 'text-indigo-700', 'hover:bg-indigo-100');
                    matchBtn.disabled = false;
                });
            }
        };
        // 键盘操作
        document.addEventListener('keydown', function(e) {
            if (!gameState || gameState.status !== 'playing') return;
            
            const snake = gameState.snakes[userId];
            if (!snake || !snake.alive) return;
            
            let newDirection = snake.direction;
            
            if ((e.key === 'a' || e.key === 'A' || e.key === 'ArrowLeft') && snake.direction !== 'RIGHT') {
                newDirection = 'LEFT';
            } else if ((e.key === 'w' || e.key === 'W' || e.key === 'ArrowUp') && snake.direction !== 'DOWN') {
                newDirection = 'UP';
            } else if ((e.key === 'd' || e.key === 'D' || e.key === 'ArrowRight') && snake.direction !== 'LEFT') {
                newDirection = 'RIGHT';
            } else if ((e.key === 's' || e.key === 'S' || e.key === 'ArrowDown') && snake.direction !== 'UP') {
                newDirection = 'DOWN';
            } else {
                return; // 无效按键或不允许反向移动
            }
            
            // 更新方向
            snake.direction = newDirection;
            
            if (!isSingleMode) {
                // 多人模式，发送方向到服务器
                sendGameOp('direction', newDirection);
            }
        });
        // 摇杆操作
        document.querySelectorAll('.joystick-btn1').forEach(btn => {
            btn.addEventListener('mousedown', function(e) {
                if (!gameState || gameState.status !== 'playing') return;
                
                const snake = gameState.snakes[userId];
                if (!snake || !snake.alive) return;
                
                const dir = this.dataset.dir;
                
                // 检查是否允许移动（不允许反向移动）
                if ((dir === 'LEFT' && snake.direction === 'RIGHT') ||
                    (dir === 'RIGHT' && snake.direction === 'LEFT') ||
                    (dir === 'UP' && snake.direction === 'DOWN') ||
                    (dir === 'DOWN' && snake.direction === 'UP')) {
                    return;
                }
                
                // 更新方向
                snake.direction = dir;
                
                if (!isSingleMode) {
                    // 多人模式，发送方向到服务器
                    sendGameOp('direction', dir);
                }
            });
            
            btn.addEventListener('touchstart', function(e) {
                if (!gameState || gameState.status !== 'playing') return;
                
                const snake = gameState.snakes[userId];
                if (!snake || !snake.alive) return;
                
                const dir = this.dataset.dir;
                
                // 检查是否允许移动（不允许反向移动）
                if ((dir === 'LEFT' && snake.direction === 'RIGHT') ||
                    (dir === 'RIGHT' && snake.direction === 'LEFT') ||
                    (dir === 'UP' && snake.direction === 'DOWN') ||
                    (dir === 'DOWN' && snake.direction === 'UP')) {
                    return;
                }
                
                // 更新方向
                snake.direction = dir;
                
                if (!isSingleMode) {
                    // 多人模式，发送方向到服务器
                    sendGameOp('direction', dir);
                }
                
                e.preventDefault();
            }, {passive: false});
        });

        // 检查所有玩家准备状态的函数
        function checkAllPlayersReadyStatus() {
            console.log("检查所有玩家准备状态");
            
            // 检查是否所有玩家都准备好了
            checkAllPlayersReady();
        }
        
        // 定义全局WebSocket消息处理函数
        window.wsMessageHandler = function(e) {
            console.log("收到原始WebSocket消息:", e.data);

            let msg = {};
            try {
                msg = JSON.parse(e.data);
                console.log("解析后的WebSocket消息类型:", msg.type, "用户ID:", msg.user_id, "内容:", msg.content);
                
                // 处理加入房间消息
                if (msg.type === MessageTypeJoin) {
                    console.log("玩家加入房间:", msg.user_id, msg.user_name);
                    // 强制更新房间用户列表
                    setTimeout(forceUpdateRoomUsers, 300);
                    return;
                }
                
                // 处理离开房间消息
                if (msg.type === MessageTypeLeave) {
                    console.log("玩家离开房间:", msg.user_id, msg.user_name);
                    // 强制更新房间用户列表
                    setTimeout(forceUpdateRoomUsers, 300);
                    return;
                }

                // 处理准备状态变更消息 (type=102)
                if (msg.type === MessageTypeReadyChanged) {
                    console.log("收到准备状态变更消息:", {
                        type: msg.type,
                        user_id: msg.user_id,
                        content: msg.content,
                        time: msg.time
                    });
                    
                    try {
                        const data = JSON.parse(msg.content);
                        console.log("解析后的准备状态变更数据:", data);

                        if (data && data.user_id !== undefined && data.ready !== undefined) {
                            console.log("准备状态变更有效数据:", data.user_id, data.ready);
                            
                            // 检查是否是当前用户自己的状态变更
                            if (data.user_id === userId) {
                                console.log("这是当前用户自己的准备状态变更，已在本地处理过，跳过");
                                // 不做额外处理，因为已经在发送时更新了本地状态
                            } else {
                                // 其他用户的状态变更，更新UI
                                console.log("更新其他用户的准备状态:", data.user_id, data.ready);
                                updatePlayerReadyStatus(data.user_id, data.ready);
                                updatePlayersUI();
                            }
                        }
                    } catch (err) {
                        console.error("解析准备状态变更消息失败:", err);
                        // 解析失败时强制更新房间信息
                        forceUpdateRoomUsers();
                    }
                    return;
                }

            } catch (err) {
                console.error("解析WebSocket消息失败:", err, e.data);
                return;
            }
            // 辅助函数：根据用户ID更新玩家卡片
            function updatePlayerCardByUserId(userId, isReady) {
                const player1Card = document.getElementById('player1-card');
                const player2Card = document.getElementById('player2-card');
                const player1Id = player1Card.getAttribute('data-user-id') || '';
                const player2Id = player2Card.getAttribute('data-user-id') || '';
                
                console.log("尝试更新玩家卡片 - 用户ID:", userId, "准备状态:", isReady);
                console.log("当前玩家卡片ID - 玩家1:", player1Id, "玩家2:", player2Id);
                
                // 根据用户ID找到对应的卡片
                if (userId === player1Id) {
                    console.log("更新玩家1卡片状态");
                    const status = document.getElementById('player1-status');
                    status.textContent = isReady ? '已准备' : '未准备';
                    player1Card.className = `player-card ${isReady ? 'ready' : 'not-ready'}`;
                    status.className = `status ${isReady ? 'ready' : ''}`;
                    
                    // 如果是当前用户，同步更新按钮状态
                    if (userId === window.userId) {
                        myReady = isReady;
                        document.getElementById('ready-btn1').textContent = isReady ? '取消准备' : '准备';
                    }
                } else if (userId === player2Id) {
                    console.log("更新玩家2卡片状态");
                    const status = document.getElementById('player2-status');
                    status.textContent = isReady ? '已准备' : '未准备';
                    player2Card.className = `player-card ${isReady ? 'ready' : 'not-ready'}`;
                    status.className = `status ${isReady ? 'ready' : ''}`;
                    
                    // 如果是当前用户，同步更新按钮状态
                    if (userId === window.userId) {
                        myReady = isReady;
                        document.getElementById('ready-btn1').textContent = isReady ? '取消准备' : '准备';
                    }
                } else {
                    console.log("找不到匹配的玩家卡片，强制更新房间信息");
                    forceUpdateReadyStatus();
                }
            }
            
            // 强制更新房间用户信息，确保准备状态同步
            if (msg.type === MessageTypeGameOp || msg.type === MessageTypeGameState || 
                msg.type === MessageTypeReadyChanged || 
                msg.type === MessageTypeJoin || msg.type === MessageTypeLeave) {
                console.log("收到需要更新用户状态的消息类型:", msg.type);
                // 延迟一点执行，确保服务器状态已更新
                setTimeout(forceUpdateRoomUsers, 100);
            }
            
            if (msg.type === MessageTypeGameOp) {
                try {
                    const data = JSON.parse(msg.content);
                    console.log("收到游戏操作:", data);
                    
                    // 检查是否是游戏开始通知
                    if (data.op === 'start_notify') {
                        console.log("收到游戏开始通知:", data);
                        // 更新游戏状态和UI
                        document.getElementById('game-tip').textContent = `${data.user_name || '对方'} 开始了游戏！`;
                        
                        // 隐藏开始按钮，显示重新开始按钮
                        document.getElementById('start-btn').classList.add('hidden');
                        document.getElementById('restart-btn').classList.add('hidden');
                        
                        // 设置游戏状态为playing
                        if (gameState) {
                            gameState.status = 'playing';
                        }
                        
                        // 启动游戏循环，不等待GameState消息
                        console.log("启动游戏循环...");
                        if (!gameInterval && !isSingleMode) {
                            gameInterval = setInterval(gameLoop, 200);
                        }
                        
                        // 强制更新一次UI
                        renderGame();
                        renderUserInfoAndScore();
                        
                        return;
                    }
                    
                    // 检查是否是开始游戏操作
                    if (data.op === 'start') {
                        console.log("收到开始游戏操作:", data);
                        // 更新游戏状态和UI
                        document.getElementById('game-tip').textContent = '游戏开始！';
                        
                        // 隐藏开始按钮，显示重新开始按钮
                        document.getElementById('start-btn').classList.add('hidden');
                        document.getElementById('restart-btn').classList.add('hidden');
                        
                        // 设置游戏状态为playing
                        if (gameState) {
                            gameState.status = 'playing';
                        }
                        
                        // 启动游戏循环
                        if (!gameInterval && !isSingleMode) {
                            gameInterval = setInterval(gameLoop, 200);
                        }
                        
                        return;
                    }
                    
                    // 检查是否是准备状态变更消息
                    if (data.op === 'ready' && data.user_id && data.ready !== undefined) {
                        console.log("收到准备状态变更(GameOp):", data.user_id, data.ready);
                        
                        // 检查是否是当前用户自己的状态变更
                        if (data.user_id === userId) {
                            console.log("这是当前用户自己的准备状态变更，已在本地处理过，跳过");
                        } else {
                            // 其他用户的状态变更，更新UI
                            console.log("更新其他用户的准备状态:", data.user_id, data.ready);
                            updatePlayerReadyStatus(data.user_id, data.ready);
                            updatePlayersUI();
                        }
                    }
                    
                    // 检查消息本身是否包含ready字段（兼容性处理）
                    if (msg.user_id && msg.ready !== undefined) {
                        console.log("从消息顶层获取准备状态:", msg.user_id, msg.ready);
                        
                        // 检查是否是当前用户自己的状态变更
                        if (msg.user_id === userId) {
                            console.log("这是当前用户自己的准备状态变更，已在本地处理过，跳过");
                        } else {
                            // 其他用户的状态变更，更新UI
                            updatePlayerReadyStatus(msg.user_id, msg.ready);
                            updatePlayersUI();
                        }
                    }
                } catch (err) {
                    console.error('解析游戏操作失败:', err, msg.content);
                    
                    // 即使解析失败，也尝试从消息顶层获取准备状态
                    if (msg.user_id && msg.ready !== undefined) {
                        console.log("解析失败但从消息顶层获取准备状态:", msg.user_id, msg.ready);
                        
                        // 检查是否是当前用户自己的状态变更
                        if (msg.user_id === userId) {
                            console.log("这是当前用户自己的准备状态变更，已在本地处理过，跳过");
                        } else {
                            // 其他用户的状态变更，更新UI
                            updatePlayerReadyStatus(msg.user_id, msg.ready);
                            updatePlayersUI();
                        }
                    }
                }
            } else if (msg.type === MessageTypeGameState) {
                try {
                    gameState = JSON.parse(msg.content);
                    console.log("收到游戏状态:", gameState);
                    
                    // 游戏状态同步时，更新UI和状态
                    if (gameState.status === 'playing') {
                        // 游戏已开始，更新UI
                        document.getElementById('game-tip').textContent = '游戏进行中...';
                        document.getElementById('start-btn').classList.add('hidden');
                        document.getElementById('restart-btn').classList.add('hidden');
                        
                        // 如果本地没有游戏循环，则启动
                        if (!gameInterval && !isSingleMode) {
                            console.log("启动游戏循环...");
                            gameInterval = setInterval(gameLoop, 200);
                        }
                    }
                    
                    renderGame();
                    renderUserInfoAndScore(); // 确保分数信息更新
                    checkMode();
                } catch (err) {
                    console.error('解析游戏状态失败:', err, msg.content);
                }
            } else if (msg.type === 'match_success' && msg.room_id) {
                // 匹配成功，跳转到新房间
                matching = false;
                matchBtn.textContent = '匹配';
                matchBtn.classList.remove('bg-gray-300', 'text-gray-500', 'bg-red-100', 'text-red-600');
                matchBtn.classList.add('bg-white', 'text-indigo-700', 'hover:bg-indigo-100');
                matchBtn.disabled = false;
                // 跳转到新房间
                window.location.href = `snake.html?room_id=${msg.room_id}`;
            } else if (msg.type === 'user_joined' || msg.type === 'user_left') {
                // 用户加入或离开时更新房间信息
                forceUpdateRoomUsers();
            }
        };
        
        // 绑定消息处理函数
        ws.onmessage = window.wsMessageHandler;

        // 返回大厅选择按钮逻辑
        let matchingInterval = null;
        let isMatching = false;

        function showMatchingModal(html) {
            let modal = document.getElementById('matching-modal');
            if (!modal) {
                modal = document.createElement('div');
                modal.id = 'matching-modal';
                modal.style = 'display:flex;position:fixed;z-index:1000;left:0;top:0;right:0;bottom:0;background:rgba(0,0,0,0.3);align-items:center;justify-content:center;';
                modal.innerHTML = `<div id='matching-modal-content' style='background:#fff;padding:2rem;border-radius:1rem;min-width:300px;'></div>`;
                document.body.appendChild(modal);
            }
            modal.style.display = 'flex';
            document.getElementById('matching-modal-content').innerHTML = html;
        }
        function hideMatchingModal() {
            const modal = document.getElementById('matching-modal');
            if (modal) modal.style.display = 'none';
        }

        function pollMatchingRooms() {
            fetch('/api/matching-rooms?type=snake')
                .then(res => res.ok ? res.json() : [])
                .then(rooms => {
                    // 过滤掉自己创建的房间
                    const userStr = localStorage.getItem('gozero_chat_user');
                    let myId = '';
                    if (userStr) {
                        try { myId = JSON.parse(userStr).userId; } catch {}
                    }
                    const otherRooms = Array.isArray(rooms) ? rooms.filter(r => r.creator_id !== myId) : [];
                    if (otherRooms.length > 0) {
                        // 展示房间卡片弹窗
                        let html = '<div class="mb-2 font-bold text-lg text-indigo-700">发现可加入的房间：</div>';
                        otherRooms.forEach(room => {
                            html += `<div class="p-3 border border-blue-300 rounded mb-2 flex justify-between items-center">
                                <span>房主: <b>${room.creator_name}</b> | 房间号: <b>${room.room_id}</b></span>
                                <button class='modern-btn px-3 py-1' onclick="window.location.href='/static/snake.html?room_id=${room.room_id}'">加入</button>
                            </div>`;
                        });
                        html += `<div class="mt-4"><button onclick="hideMatchingModal();isMatching=false;matchBtn.textContent='匹配';if(matchingInterval)clearInterval(matchingInterval);" class="modern-btn bg-gray-200 text-gray-700">取消</button></div>`;
                        showMatchingModal(html);
                    } else {
                        showMatchingModal('<div class="text-center text-lg text-indigo-700">正在匹配...</div>');
                    }
                });
        }
    </script>
</body>
</html>